package awk.lock;

import awk.thread.ThreadPoolUtils;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 1. ReadWriteLock : 读写锁
 * 写写/读写 需要“互斥”
 * 读读 不需要互斥
 * 2.线程正在读，写线程需要等待读线程释放锁后才能获取写锁，即读的过程中不允许写，这是一种悲观的读锁。要进一步提升并发执行效率，Java 8引入了新的读写锁：StampedLock。
 *
 * StampedLock和ReadWriteLock相比，改进之处在于：读的过程中也允许获取写锁后写入！这样一来，我们读的数据就可能不一致，所以，需要一点额外的代码来判断读的过程中是否有写入，
 * 这种读锁是一种乐观锁。
 * 乐观锁的意思就是乐观地估计读的过程中大概率不会有写入，因此被称为乐观锁。反过来，悲观锁则是读的过程中拒绝有写入，也就是写入必须等待。
 * 显然乐观锁的并发效率更高，但一旦有小概率的写入导致读取的数据不一致，需要能检测出来，再读一遍就行。
 */
public class ReadWriteLockTest {

    public static void main(String[] args) {
        ReadWriteLockDemo rw = new ReadWriteLockDemo();

        ThreadPoolExecutor pool = ThreadPoolUtils.getPool();
        pool.execute(() -> rw.set((int) (Math.random() * 101)));
        pool.execute(rw::get);
    }

    static class ReadWriteLockDemo {
        private int number = 0;
        private ReadWriteLock lock = new ReentrantReadWriteLock();

        public void get() {
            lock.readLock().lock(); //上锁
            try {
                System.out.println(Thread.currentThread().getName() + " : " + number);
            } finally {
                lock.readLock().unlock(); //释放锁
            }
        }

        public void set(int number) {
            lock.writeLock().lock();
            try {
                System.out.println(Thread.currentThread().getName());
                this.number = number;
            } finally {
                lock.writeLock().unlock();
            }
        }
    }
}

